package pay

import (
	"context"
	"gitee.com/CrazyMage/blog-service/global"
	"github.com/smartwalle/alipay/v3"
	"log"
)

type PreCreateReq struct {
	OutTradeNo  string `json:"out_trade_no"`
	TotalAmount string `json:"total_amount"`
	Subject     string `json:"subject"`
	ProductCode string `json:"product_code"`
}

type PreCreateResp struct {
	OutTradeNo string `json:"out_trade_no"`
	QRCode     string `json:"qr_code"`
}

type QueryReq struct {
	OutTradeNo string `form:"out_trade_no" json:"out_trade_no"`
	TradeNO    string `form:"trade_no" json:"trade_no"`
}

type QueryResp struct {
	OutTradeNo  string `json:"out_trade_no"`
	TradeNO     string `json:"trade_no"`
	TradeState  string `json:"trade_state"`
	TotalAmount string `json:"total_amount"`
}

type RefundReq struct {
	RefundAmount string `json:"refund_amount"`
	OutTradeNo   string `json:"out_trade_no"`
	TradeNO      string `json:"trade_no"`
	OutRequestNo string `json:"out_request_no"`
}

type RefundResp struct {
	TradeNo      string `json:"trade_no"`
	OutTradeNo   string `json:"out_trade_no"`
	BuyerLogonId string `json:"buyer_logon_id"`
	RefundFee    string `json:"refund_fee"`
}

type RefundQueryReq struct {
	OutRequestNo string `form:"out_request_no" json:"out_request_no"`
	TradeNO      string `form:"trade_no" json:"trade_no"`
	OutTradeNo   string `form:"out_trade_no" json:"out_trade_no"`
}

type RefundQueryResp struct {
	TradeNO      string `json:"trade_no"`
	OutTradeNo   string `json:"out_trade_no"`
	OutRequestNo string `json:"out_request_no"`
	TotalAmount  string `json:"total_amount"`
	RefundAmount string `json:"refund_amount"`
	ReFundStatus string `json:"re_fund_status"`
}

type AliPayNotifyReq struct {
	TradeNO      string `form:"trade_no" json:"trade_no"`
	out_trade_no string `form:"out_trade_no" json:"out_trade_no"`
	trade_status string `form:"trade_status" json:"trade_status"`
}

type AliPay struct {
	context context.Context
	client  *alipay.Client
}

func NewAliPayClient(ctx context.Context) (*AliPay, error) {

	var err error
	setting := global.AliPayClientSetting
	var client *alipay.Client
	// 初始化支付宝客户端
	client, err = alipay.New(setting.AppId, setting.AppPrivateKey, false)

	// 加载支付宝公钥
	err = client.LoadAliPayPublicKey(setting.AliPayPublicKey)
	if err != nil {
		log.Fatal("加载支付宝公钥失败:", err)
	}
	return &AliPay{
		context: ctx,
		client:  client,
	}, nil
}

func (ap *AliPay) GetOriginalClient() *alipay.Client {
	return ap.client

}

func (ap *AliPay) PreCreate(req *PreCreateReq) (PreCreateResp, error) {

	create, err := ap.client.TradePreCreate(ap.context, alipay.TradePreCreate{
		Trade: alipay.Trade{
			OutTradeNo:  req.OutTradeNo,
			TotalAmount: req.TotalAmount,
			Subject:     req.Subject,
			ProductCode: req.ProductCode,
			NotifyURL:   global.AliPayClientSetting.NotifyURL,
		},
	})
	if err != nil {
		return PreCreateResp{}, err
	}

	if create.Error.Msg != "Success" {
		return PreCreateResp{}, create.Error
	}

	return PreCreateResp{
		OutTradeNo: create.OutTradeNo,
		QRCode:     create.QRCode,
	}, nil
}
func (ap *AliPay) Query(req *QueryReq) (QueryResp, error) {

	query, err := ap.client.TradeQuery(ap.context, alipay.TradeQuery{
		OutTradeNo: req.OutTradeNo,
		TradeNo:    req.TradeNO,
	})
	if err != nil {
		return QueryResp{}, err
	}

	if query.Error.Msg != "Success" {
		return QueryResp{}, query.Error
	}

	return QueryResp{
		OutTradeNo:  query.OutTradeNo,
		TradeNO:     query.TradeNo,
		TradeState:  string(query.TradeStatus),
		TotalAmount: query.TotalAmount,
	}, nil

}

func (ap *AliPay) Refund(req *RefundReq) (RefundResp, error) {
	refund, err := ap.client.TradeRefund(ap.context, alipay.TradeRefund{
		RefundAmount: req.RefundAmount,
		OutTradeNo:   req.OutTradeNo,
		TradeNo:      req.TradeNO,
		OutRequestNo: req.OutRequestNo,
	})
	if err != nil {
		return RefundResp{}, err
	}

	if refund.Error.Msg != "Success" {
		return RefundResp{}, refund.Error
	}

	return RefundResp{
		TradeNo:      refund.TradeNo,
		OutTradeNo:   refund.OutTradeNo,
		BuyerLogonId: refund.BuyerLogonId,
		RefundFee:    refund.RefundFee,
	}, nil
}

func (ap *AliPay) RefundQuery(req *RefundQueryReq) (RefundQueryResp, error) {

	refundQuery, err := ap.client.TradeFastPayRefundQuery(ap.context, alipay.TradeFastPayRefundQuery{
		TradeNo:      req.TradeNO,
		OutTradeNo:   req.OutTradeNo,
		OutRequestNo: req.OutRequestNo,
	})
	if err != nil {
		return RefundQueryResp{}, err
	}

	if refundQuery.Error.Msg != "Success" {
		return RefundQueryResp{}, refundQuery.Error
	}

	return RefundQueryResp{
		TradeNO:      refundQuery.TradeNo,
		OutTradeNo:   refundQuery.OutTradeNo,
		OutRequestNo: refundQuery.OutRequestNo,
		TotalAmount:  refundQuery.TotalAmount,
		RefundAmount: refundQuery.RefundAmount,
		ReFundStatus: refundQuery.RefundStatus,
	}, nil

}
